<?php

use \Nette\Templates\TemplateFilters;

/**
 * @property-read \Tasker\Configurator\ServiceFactories $context
 */
abstract class BasePresenter extends \Nette\Application\UI\Presenter
{

	protected static $mustLogin = true;
	protected static $dateFormatLong = "j.n.Y";

	protected function startup()
	{
		parent::startup();
		$usersModel = $this->context->models->users;
		$panel = \Panel\User::register();
		$panel->setNameColumn('login');
		foreach ($usersModel->getUsers() as $user)
		{
			$panel->addCredentials($user['login'], 'heslo');
		}
	}

	protected function beforeRender()
	{
		parent::beforeRender();
		if (self::$mustLogin && !$this->getUser()->isLoggedIn())
		{
			$this->redirect(':Sign:in');
		}
		$this->template->dateFormatLong = self::$dateFormatLong;
		$taskContext = $this->context->models->taskContext;
		$this->template->statuses = $taskContext->getStatuses();
	}

	public function handleUpdateStatus($task, $status)
	{
		$taskModel = $this->context->models->task->find($task);
		$taskModel->setStatus($status, $this->user->id);
		$this->redirect('this');
	}

	public function handleUpdateCompleted($task, $completed)
	{
		$taskModel = $this->context->models->task->find($task);
		$taskModel->setCompleted($completed, $this->user->id);

		$this->redirect('this');
	}

	public function handleUpdateUserPriority($task, $priority)
	{
		$taskModel = $this->context->models->task->find($task);
		$taskModel->getTask()->update(array('userpriority' => $priority));
		$this->redirect('this');
	}

	public function handleSwitchWatched($id)
	{
		$tasksModel = $this->context->models->tasks;
		$watched = $tasksModel->getWatched(array('user_id' => $this->user->id, 'task_id' => $id));
		if (count($watched) > 0)
		{
			$tasksModel->deleteWatched($this->user->id, $id);
		} else
		{
			$tasksModel->addWatched($this->user->id, $id);
		}
		$this->redirect('this');
	}

	protected function createTemplate($class = NULL)
	{
		$template = parent::createTemplate();
		$template->registerHelper('remaining_days', function($s)
				{
					$remaining = ceil((strtotime($s) - time()) / 60 / 60 / 24);
					if ($remaining == 0)
						$remaining = 0; // avoid -0
					$str = "dnů";
					if (abs($remaining) == 1)
						$str = "den";
					if (abs($remaining) > 1 && abs($remaining) < 5)
						$str = "dny";
					if ($remaining > 7)
						$class = 'task_ok';
					elseif ($remaining >= 0)
						$class = 'task_hurry';
					else
						$class='task_late';
					return '<span class="' . $class . '">' . $remaining . " " . $str . '</span>';
				});
		$that = $this; // php 5.3 hack		
		$template->registerHelper('bool2image', function($s) use ($that)
				{
					$basePath = $that->context->params['basePath'];
					$value = null;
					if (is_bool($s))
					{
						$value = $s;
					} elseif (is_string($s))
					{
						if ($s === 'yes')
						{
							$value = true;
						} elseif ($s === 'no')
						{
							$value = false;
						}
					}
					if ($value !== null)
					{
						$el = Nette\Utils\Html::el('img')
								->src($basePath . '/images/admin/' . ($value ? 'yes' : 'no') . '.png');
						return $el;
					}
					return null;
				});

		$template->registerHelper('czMonth', function($s)
				{
					static $months = array(1 => 'Leden', 'Únor', 'Březen', 'Duben', 'Květen',
				'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec');
					return $months[$s];
				});
		$template->registerHelper('shortPath', function($s) use ($that)
				{
					$base = $that->context->params['uploadDirBase'];
					$shortPath = substr($s, strlen($base));
					return '…'.$shortPath;
				});
		// inicializace Texy
		$texy = new \Texy();
		$texy->encoding = 'utf-8';
		$texy->allowedTags = \Texy::NONE;
		$texy->allowedStyles = \Texy::NONE;
		$texy->setOutputMode(\Texy::HTML5);

		// registrace filtru
		$template->registerHelper('texy', callback($texy, 'process'));
		return $template;
	}

	public function templatePrepareFilters($template)
	{
		$template->registerFilter($latte = new \Nette\Latte\Engine);
		$set = \Nette\Latte\Macros\MacroSet::install($latte->parser);
		$set->addMacro('forIn', function($s)
				{
					$args = explode("..", $s->args);
					return 'for($i=' . $args[0] . ';$i<=' . $args[1] . ';$i++):' . "\n";
				}, 'endfor;');
	}

	public function signalReceived($signal)
	{
		$methodName = $this->formatSignalMethod($signal);
		if (method_exists($this, $methodName))
		{
			$method = $this->getReflection()->getMethod($methodName);
			if ($method->hasAnnotation('secured'))
			{
				$protectedParams = array();
				foreach ($method->getParameters() as $param)
				{
					$protectedParams[$param->name] = $this->getParam($param->name);
				}
				if ($this->getParam('__secu') !== $this->createSecureHash($protectedParams))
				{
					throw new Nette\Application\UI\BadSignalException('Secured parameters are not valid.');
				}
			}
		}

		parent::signalReceived($signal);
	}

	public function link($destination, $args = array())
	{

		if (!is_array($args))
		{
			$args = func_get_args();
			array_shift($args);
		}

		$link = parent::link($destination, $args);
		$lastrequest = $this->presenter->lastCreatedRequest;

		/* --- Bad link --- */
		if ($lastrequest === NULL)
		{
			return $link;
		}

		/* --- Not a signal --- */
		if (substr($destination, - 1) !== '!')
		{
			return $link;
		}

		/* --- Only on same presenter --- */
		if ($this->getPresenter()->getName() !== $lastrequest->getPresenterName())
		{
			return $link;
		}

		$signal = trim($destination, '!');
		try
		{
			$rc = $this->getReflection()->getMethod($this->formatSignalMethod($signal));
		} catch (ReflectionException $e)
		{
			return $link;
		}

		if ($rc->hasAnnotation('secured') === FALSE)
		{
			return $link;
		}

		$origParams = $lastrequest->getParams();
		$protectedParams = array();

		foreach ($rc->getParameters() as $param)
		{
			$protectedParams[$param->name] = Nette\Utils\Arrays::get($origParams, $this->getParamId($param->name));
		}
		$args['__secu'] = $this->createSecureHash($protectedParams);
		return parent::link($destination, $args);
	}

	protected function createSecureHash($params)
	{
		$ns = $this->context->container->session->getSection('securedlinks');
		if ($ns->key === NULL)
		{
			$ns->key = uniqid();
		}
		$s = implode('|', array_keys($params)) . '|' . implode('|', array_values($params)) . $ns->key;
		return substr(md5($s), 4, 8);
	}

}
